/**
 *
 */
Function.prototype.bind = function(context){
    var slice = Array.prototype.slice;

    function update(array, args){
        var arrayLength = array.length, length = args.length;
        while(length--)
            array[arrayLength+length] = args[length];
        return array;
    }

    function merge(array, args){
        array = slice.call(array, 0);

        return update(array, args);
    }

    if(arguments.length < 2 && typeof arguments[0] === "undefined") return this;

    var __method = this, args = slice.call(arguments, 1);

    return function(){
        var a = merge(args, arguments);
        return __method.apply(context, a);
    }
}

function extend(dest, src){
    for(var name in src){
        dest[name] = src[name];
    }
}

function FMAjaxClient(options){
    this._options = options;
    this.initialize();
}

extend(FMAjaxClient.prototype, {
    xhr: {},
    fmMethod: "",
    httpMethod: "GET",
    params: {},
    url: "/_rest/api.php",
    initialize: function(){
        if(this._options && this._options.fmMethod)
            this.fmMethod = this._options.fmMethod;
        else
            this.fmMethod = "fm.photos.getCurrentPhotos";

        if(this._options && this._options.httpMethod)
            this.httpMethod = this._options.httpMethod;

        if(this._options && this._options.url)
            this.url = this._options.url;

        this.url = this.url.indexOf("?")>0?(this.url+"&method="+this.fmMethod):(this.url+"?method="+this.fmMethod);

        this.xhr = this._createXMLHttpRequest();
    },
    _createXMLHttpRequest: function(){
        try{return new XMLHttpRequest();}catch(e){}
        try{return new ActiveXObject("Msxml2.XMLHTTP");}catch(e){}
        try{return new ActiveXObject("Microsoft.XMLHTTP");}catch(e){}
        return null;
    },
    _setHttpHeaders: function(){
        var headers = {
            "X-Request-With": "XMLHttpRequest",
            "X-FM-Version": "1.0",
            "Accecpt": "text/javascript, text/html, application/xml, text/xml, */*"
        };
        if(this.httpMethod.toLowerCase()=="post"){
            headers["Content-type"] = "application/x-www-form-urlencode; charset=UTF-8";
            if(this.xhr && this.xhr.overrideMimeType && (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0, 2005])[1]<2005){
                headers["Connection"] = "close";
            }
        }
        for(var name in headers){
            if(this.xhr){
                this.xhr.setRequestHeader(name, headers[name])
            }
        }
    },
    _getStatus: function(){
        try{
            if(this.xhr.status == 1223) return 204;
            return this.xhr.status || 0;
        }catch(e){return 0}
    },
    _getHeader: function(name){
        try{
            return this.xhr.getResponseHeader(name)
        }catch(e){return null}
    },
    setParams: function(params){
        extend(this.params, params);
    },
    setCallback: function(fn){
        if(typeof fn !== "function")
            return;
        this._callback = fn;
    },
    request: function(){
        if(this.xhr){
            this.xhr.open(this.httpMethod.toUpperCase(), this._generateURL(), true);
            this._setHttpHeaders();
            this.xhr.onreadystatechange = this._onreadystatechange.bind(this);
            this.body = this.httpMethod.toLowerCase()=="post"?this._toQueryString():null;
            this.xhr.send(this.body);
        }
    },
    _generateURL: function(){
        if(this.httpMethod.toLowerCase()=="post"){
            this.queryString = this._toQueryString();
            return this.url;
        }else{
            return this.url + "&" + this._toQueryString();
        }
    },
    _toQueryString: function(){
        var params = new Array();
        for(var name in this.params)
            params.push(name+"="+encodeURIComponent(this.params[name]));

        return params.join("&");
    },
    success: function(){
        var status = this._getStatus();
        return !status || (status>=200 && status<300) || status==304;
    },
    _onreadystatechange: function(){
        var readyState = this.xhr.readyState;
        if(readyState>1 && !(readyState==4))
            this._respondToReadyState(readyState);
        else if(readyState==4 && this.success()){
            var data = JSON.parse(this.xhr.responseText);
            this._callback(data);
        }
    },
    _callback: function(data){

    },
    _respondToReadyState: function(state){
        
    }
});


function FMClient(){
    this.initialize();
}

extend(FMClient.prototype, {
    _version: 1.0,
    _currentKey: "",
    _supportDatabase: false,
    _supportLocalStorage: false,
    _localStoreKey: "_fm_store",
    _currentImgKey: "_ci",
    _dbConn: null,
    _today: "",
    _currentImage: "",
    _currentIndex: 0,
    _length: 0,
    _animationList: ['fade', 'dissolve', 'pop', 'slideleft', 'slideright', 'slideup', 'slidedown', 'flipleft', 'flipright', 'swapright', 'swapleft', 'cubeleft', 'cuberight'],
    _browser: {
        ie: false,
        safari: false,
        opera: false,
        firefox: false
    },
    _platform: {
        win32: false,
        linux: false
    },
    initialize: function(){
        var cont = this.initializeVars();
        if(!cont)
            return;
        if(!this.checkImage()){
            return;
        }

        this.loadNewImage();
    },
    initializeVars: function(){
        this._supportDatabase = !!window.openDatabase;
        this._supportLocalStorage = !!window.localStorage;
        if(this._supportDatabase)
            this._dbConn = window.openDatabase("FMStore", "1.0", "Offline store", 5*1024*1024);

        if(!this._supportDatabase && this._supportLocalStorage){
            
        }

        if(!this._supportDatabase && !this._supportLocalStorage){
            return false;
        }
        if(this._supportLocalStorage){
            this._currentImage = localStorage.getItem(this._currentImgKey);
        }
        var date = new Date();
        this._today = ""+date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate();
        return true;
    },
    checkImage: function(){
        if(this._supportDatabase){
            this._ensureTables();
            return true;
        }else if(this._supportLocalStorage){
            
            return true;
        }else{
            return false;
        }
    },
    _ensureTables: function(){
        var self = this;
        if(this._supportDatabase){
            this._dbConn.transaction(function(context){
                context.executeSql("SELECT * FROM fm_photos", [], function(t, s){
                    
                }, function(tx, error){
                    self._dbConn.transaction(function(ctx){
                        ctx.executeSql("CREATE TABLE IF NOT EXISTS fm_photos('id' INTEGER PRIMARY KEY AUTOINCREMENT, 'name' VARCHAR(255), 'url' VARCHAR(500), 'key' VARCHAR(255), 'copy_info' VARCHAR(1000), 'region' VARCHAR(100), 'fm_date' VARCHAR(20))", [], function(c, r){

                    }, function(c, e){
                    });
                    })
                });
            });
        }
    },
    loadNewImage: function(){
        var self = this;
        if(this._supportDatabase){
            this._dbConn.transaction(function(context){
                context.executeSql("SELECT * FROM fm_photos WHERE fm_date=?", [self._today], function(t, r){
                    if(r.rows.length==0){
                        self.requestTodayImage();
                    }else{
                        self.renderUI();
                    }
                }, function(e,f){
                    
                })
            })
        }
    },
    requestTodayImage: function(){
        var client = new FMAjaxClient({});
        var self = this;
        client.setCallback(function(data){
            
            var i = 0;
            if(self._supportLocalStorage && !self._currentImage){
                if(data.output.length){
                    self._currentImage = data.output[i].key;
                    localStorage.setItem(self._currentImgKey, self._currentImage);
                }
            }
            function pushData(index){
                var image = data.output[index];
                var sql = "INSERT INTO fm_photos('name', 'url', 'key', 'copy_info', 'region', 'fm_date') VALUES('"+image.name+"', '"+image.url+"', '"+image.key+"', '"+image.copy_info+"', '"+image.country_region+"', '"+self._today+"')";
                self._dbConn.transaction(function(context){
                    context.executeSql(sql, [], function(tx, r){
                        i++;
                        if(i==data.output.length)
                            self.renderUI();
                        else
                            pushData(i);
                    }, function(tx, er){
                        i++;
                        if(i==data.output.length)
                            self.renderUI();
                        else
                            pushData(i);
                    });
                }, function(a, b){
                    i++;
                    if(i==data.output.length)
                        self.renderUI();
                    else
                        pushData(i);
                });
            }
            if(data.output.length>0)
                pushData(i);
            else
                self.renderUI();
        });
        client.request();
    },
    renderUI: function(){
        var self = this;
        this._dbConn.transaction(function(context){
            context.executeSql("SELECT * FROM fm_photos ORDER BY id", [], function(tx, result){
                if(self._supportLocalStorage && !self._currentImage){
                    if(result.rows.length){
                        var item = result.rows.item(0);
                        self._currentImage = item["key"];
                        localStorage.setItem(self._currentImgKey, self._currentImage);
                    }
                }
                self._length = result.rows.length;
                for(var i = 0; i<result.rows.length; i++){

                    var imgData = result.rows.item(i);
                    var imgItem = document.createElement("DIV");
                    imgItem.setAttribute("xkey", imgData["key"]);
                    imgItem.setAttribute("index", i);
                    imgItem.setAttribute("id", "item"+i);
                    imgItem.setAttribute("xurl", imgData["url"]);
                    if(imgData["key"] == self._currentImage){
                        self._currentIndex = i;
                        imgItem.setAttribute("class", "current");
                        self.recordImpression(self._currentImage);
                    }
                    var image = document.createElement("IMG");
                    image.setAttribute("src", imgData["url"]);
                    image.setAttribute("alt", imgData["copy_info"]);
                    imgItem.appendChild(image);
                    var info = document.createElement("DIV");
                    info.setAttribute("class", "info-tip");
                    info.innerHTML = imgData["copy_info"];
                    imgItem.appendChild(info);
                    document.body.appendChild(imgItem);
                    imgItem.addEventListener("webkitAnimationEnd", function(){
                        var state = this.getAttribute("state");
                        if(state == "current")
                            this.setAttribute("class", null);
                        else if(state == "next"){
                            this.setAttribute("class", "current");
                            self._currentIndex = Number(this.getAttribute("index"));
                            localStorage.setItem(self._currentImgKey, this.getAttribute("xkey"));
                            self.recordImpression(this.getAttribute("xkey"));
                        }
                    }, false);
                    imgItem.addEventListener("click", function(){
                        var index = Number(this.getAttribute("index"));
                        var nextIndex = index+1>self._length-1?0:index+1;
                        var cnode = document.getElementById("item"+index);
                        var nnode = document.getElementById("item"+nextIndex);
                        var anIndex = Math.round(Math.random()*20)%13;
                        var aniName = self._animationList[anIndex];
                        if(cnode && nnode){
                            cnode.setAttribute("class", "current "+aniName+" out");
                            cnode.setAttribute("state", "current");
                            nnode.setAttribute("class", "current "+aniName+" in");
                            nnode.setAttribute("state", "next");
                        }
                    }, false);
                }
            });
        });
    },
    recordImpression: function(key){
        var client = new FMAjaxClient({fmMethod: "fm.impressions.incr"});
        client.setParams({key:key});
        client.request();

    }
});